package main

import (
	"fmt"
	"log"
	"net/http"

	"time"

	"encoding/json"

	"sync"

	"github.com/coreos/etcd/client"
	"golang.org/x/net/context"
)

type OneNode struct {
	Key   string
	Value string
}

func Worker(res *[]OneNode, MU *sync.RWMutex, ns client.Nodes) {
	var AppendNode = func(i OneNode) {
		MU.Lock()
		defer MU.Unlock()
		*res = append(*res, i)
	}

	for _, v := range ns {
		if v.Dir {
			Worker(res, MU, v.Nodes)
		} else {
			AppendNode(OneNode{
				Key:   v.Key,
				Value: v.Value,
			})
		}
	}
}

func Get(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	r.ParseForm()

	EndPoint := r.FormValue("EndPoint")
	if EndPoint == "" {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("short of parameter EndPoint"))
		return
	}
	DirPath := r.FormValue("Dir")
	if DirPath == "" {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("short of parameter Dir"))
		return
	}
	cfg := client.Config{
		Endpoints: []string{EndPoint},
		Transport: client.DefaultTransport,
		// set timeout per request to fail fast when the target endpoint is unavailable
		HeaderTimeoutPerRequest: time.Second,
	}
	c, err := client.New(cfg)
	if err != nil {
		log.Fatal(err)
	}
	kapi := client.NewKeysAPI(c)
	resp, err := kapi.Get(context.Background(), DirPath, &client.GetOptions{
		Recursive: true,
		Sort:      true,
	})
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Println("Error occur:", err.Error())
		return
	}

	res := []OneNode{}
	var MU sync.RWMutex

	if resp.Node.Dir {
		Worker(&res, &MU, resp.Node.Nodes)
	} else {
		res = append(res, OneNode{
			Key:   resp.Node.Key,
			Value: resp.Node.Value,
		})
	}

	b, err := json.Marshal(res)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Write(b)
}

func main() {
	http.HandleFunc("/etcd/get", Get)

	fmt.Println("你妈炸了")

	log.Fatal(http.ListenAndServe(":8089", nil))
}
